import type { model_meta } from '../types/global'
import type { TableColumnCtx } from 'element-plus'

import { format } from 'date-fns'
import { useDbStore } from '@/stores/modules/database'
import { e_code_prefix, e_store_tag, e_store_type } from '@/types/enum'
export function isValidKey(key: string | undefined, object: object): key is keyof typeof object {
  if (!key) return false
  return key in object
}

export function trySetValue(object: object, key: string, value: any): key is keyof typeof object {
  if (isValidKey(key, object)) {
    ;(<typeof value>object[key]) = value //ref https://juejin.cn/post/6844903973330092045
    return true
  }
  return false
}

export const fill_ref_info = <T extends object>(data: T[], metas: model_meta[]) => {
  const dbStore = useDbStore()
  const promises: Promise<void>[] = []
  metas
    .filter((r) => r.ref_args)
    .forEach((meta) => {
      const promise: Promise<void> = new Promise<void>((resolve, reject) => {
        const key = meta.ref_args?.jsonPath
        if (isValidKey(key, dbStore)) {
          const ref_records = dbStore[key] as Object[]
          data.forEach((item) => {
            if (isValidKey(meta.code, item)) {
              const itemCode = item[meta.code] as string
              const ref_item = ref_records.find((_item) => {
                const ref_code_field = meta.ref_args?.codeField
                if (ref_code_field && isValidKey(ref_code_field, _item)) {
                  return _item[ref_code_field] === itemCode
                }
                return false
              })
              if (ref_item) trySetValue(item, meta.code, ref_item)
            }
          })
          resolve()
        }
        reject()
      })
      promises.push(promise)
    })
  return Promise.all(promises)
}

export const cell_formatter = (column: TableColumnCtx<any>, cellValue: any, metas: model_meta[]) => {
  const arg = metas.find((r) => r.code === column.property)
  if (typeof cellValue === 'object' && arg?.text_field && isValidKey(arg?.text_field, cellValue)) {
    return cellValue[arg?.text_field]
  }
  const _ref_arg = arg?.ref_args
  if (!_ref_arg && typeof cellValue === 'boolean') {
    return cellValue ? '是' : '否'
  }

  const _options_enum = arg?.options_enum
  if (_ref_arg) {
    if (typeof cellValue === 'string') return cellValue
    else return cellValue[_ref_arg.textField]
  }

  if (_options_enum) {
    if (arg?.mult) {
      let r = ''
      for (const key in _options_enum) {
        if (_options_enum[key] === cellValue) return key
        else if ((_options_enum[key] & cellValue) === _options_enum[key] && _options_enum[key] !== 0) {
          if (r.length > 0) r += '|'
          r += key
        }
      }
      return r
    } else {
      for (const key in _options_enum) {
        if (_options_enum[key] === cellValue) return key
      }
    }
    return cellValue
  }
  return cellValue
}

let seq = 1
export const make_billcode = (prefix?: string) => {
  const date = format(new Date(), 'yyMMdd')
  const s2 = 100 + Math.floor(Math.random() * 100)
  const s3 = 100 + seq++
  const s = date + s2.toString().substring(1, 3) + s3.toString().substring(1, 3)
  if (prefix) return prefix + s
  else return s
}
export const today = () => {
  return format(new Date(), 'yyyy-MM-dd')
}
export const sum = (numbers: number[] | undefined) => {
  let s = 0
  if (!numbers) return 0
  for (let i = numbers.length - 1; i >= 0; i--) {
    s += numbers[i]
  }
  return s
}
export const max = (numbers: number[] | undefined) => {
  let s = 0
  if (!numbers) return 0
  for (let i = numbers.length - 1; i >= 0; i--) {
    s = Math.max(numbers[i], s)
  }
  return s
}
export const distinct = <T>(arr?: T[]) => {
  if (!arr) return []
  if (arr.length === 0) return []
  if (typeof arr[0] === 'object') {
    const arr_as_json = arr.map((r) => {
      return JSON.stringify(r)
    })
    const result_as_json = [...new Set(arr_as_json)]
    return result_as_json.map((r) => {
      return JSON.parse(r)
    })
  }
  return [...new Set(arr)]
}

export const compare_obj = <T>(obj1: T | string, obj2: T | string, key: keyof T) => {
  const val1 = typeof obj1 === 'string' ? obj1 : obj1[key]
  const val2 = typeof obj2 === 'string' ? obj2 : obj2[key]
  return val1 === val2
}

export const get_code_prefix = (qr_str: string) => {
  for (const x in e_code_prefix) {
    if (qr_str.startsWith(e_code_prefix[x as keyof typeof e_code_prefix])) return x
  }
  return '其他'
}

export const store_type_check = (loc_type: number, mtl_type: e_store_type) => {
  if (loc_type === e_store_type.不限制) return true
  return (loc_type & mtl_type) === mtl_type
}
export const store_tag_check = (loc_tag: number, mtl_tag: e_store_tag) => {
  if (loc_tag === e_store_tag.无特殊) return true
  return (loc_tag & mtl_tag) === mtl_tag
}
